package ro.upt.ac.cstaicu.analyze;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

import ro.upt.ac.cstaicu.execution.TestResult;

public abstract class SpectrumBasedFLTechnique implements FaultLocalisationTechnique {
 
	@Override
	public ArrayList<FaultLocalizationEntity> rankEntities(
			Collection<Entity> reachedEntities, Collection<TestResult> tests) {
		ArrayList<FaultLocalizationEntity> result = new ArrayList<FaultLocalizationEntity>();
		double passed = 0; 
		double failed = 0;
		
		for (TestResult test : tests) {
			
			if (test.failed())
				failed++;
			else 
				passed++;
			
		}		
		
		for (Entity e : reachedEntities) {
			double souspiciusness;
			if (failed == 0)
				souspiciusness = 0;
			else if (passed == 0)
				souspiciusness = 1;
			else if (e.getNoFailed() == 0)
				souspiciusness = 0;				
			else
				souspiciusness = computeSuspiciousness(e, passed, failed);
			result.add(new FaultLocalizationEntity(e, souspiciusness));
			
		}	
		Collections.sort(result);
		return result;
	}
	
	@Override
	public Collection<FaultLocalizationEntity> rankSingleErrorEntities(
			Collection<Entity> entities, ArrayList<TestResult> testResults,
			TestResult error) {
		
		ArrayList<FaultLocalizationEntity> result = new ArrayList<FaultLocalizationEntity>();
		double passed = 0;
		
		for (TestResult test : testResults) {
			
			if (!test.failed())
				passed++;
			
		}		

		for (Entity e : entities) {
			double souspiciusness;
			if (passed == 0)
				souspiciusness = 1;
			else if (!e.reachedByTest(error))
				souspiciusness = 0;				
			else
				souspiciusness = computeSuspiciousnessSingleError(e, passed);
			result.add(new FaultLocalizationEntity(e, souspiciusness));
//			System.out.println(e.info + " " + e.getNoFailed() + " " + e.getNoPassed() + " " + souspiciusness);
			
		}	
		Collections.sort(result);
		return result;
	}
	
	public abstract double computeSuspiciousness(Entity e, double totalPassed, double totalFailed);
	public abstract double computeSuspiciousnessSingleError(Entity e, double totalPassed);
}
